<template>
    <div class="upload-file">
        <el-upload
            multiple
            :action="uploadFileUrl"
            :before-upload="handleBeforeUpload"
            :file-list="fileList"
            :limit="limit"
            :on-error="handleUploadError"
            :on-exceed="handleExceed"
            :on-success="handleUploadSuccess"
            :show-file-list="false"
            :headers="headers"
            class="upload-file-uploader"
            ref="fileUpload"
        >
            <el-button type="primary">选取文件</el-button>
        </el-upload>

        <div class="el-upload__tip" v-if="showTip">
            请上传
            <template v-if="fileSize">
                大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b>
            </template>
            <template v-if="fileType.length">
                格式为 <b style="color: #f56c6c">{{ fileType.join("/") }}</b>
            </template>
            的文件
        </div>

        <transition-group
            class="upload-file-list el-upload-list el-upload-list--text"
            name="el-fade-in-linear"
            tag="ul"
        >
            <li
                v-for="(file, index) in fileList"
                :key="file.uid"
                class="el-upload-list__item ele-upload-list__item-content"
            >
                <el-link :href="file.url" :underline="false" target="_blank">
                    <span class="el-icon-document"> {{ getFileName(file.name) }} </span>
                </el-link>
                <div class="ele-upload-list__item-content-action">
                    <el-link :underline="false" @click="handleDelete(index)" type="danger"
                    >删除</el-link
                    >
                </div>
            </li>
        </transition-group>
    </div>
</template>

<script>
import { listByIds, delOss } from "@/api/oss";
import { getToken } from "@/utils/auth";
import { Message } from "element-ui";

export default {
    name: "UploadFile",
    props: {
        modelValue: [String, Object, Array],
        limit: {
            type: Number,
            default: 5,
        },
        fileSize: {
            type: Number,
            default: 5,
        },
        fileType: {
            type: Array,
            default: () => ["doc", "xls", "ppt", "txt", "pdf"],
        },
        isShowTip: {
            type: Boolean,
            default: true,
        },
    },
    data() {
        return {
            number: 0,
            uploadList: [],
            fileList: [],
            baseUrl: process.env.VUE_APP_BASE_API,
        };
    },
    computed: {
        uploadFileUrl() {
            return this.baseUrl + "/oss/upload";
        },
        headers() {
            return { Authorization: "Bearer " + getToken() };
        },
        showTip() {
            return this.isShowTip && (this.fileType.length || this.fileSize);
        },
    },
    watch: {
        modelValue: {
            handler: "initFileList",
            deep: true,
            immediate: true,
        },
    },
    methods: {
        async initFileList(val) {
            if (!val) {
                this.fileList = [];
                return;
            }
            let list = [];
            if (Array.isArray(val)) {
                list = val;
            } else {
                try {
                    const res = await listByIds(val);
                    list = res.data.map((oss) => ({
                        name: oss.originalName,
                        url: oss.url,
                        ossId: oss.ossId,
                    }));
                } catch (e) {
                    console.error("Failed to fetch files by ID:", e);
                }
            }
            let temp = 1;
            this.fileList = list.map((item) => ({
                ...item,
                uid: item.uid || new Date().getTime() + temp++,
            }));
        },
        handleBeforeUpload(file) {
            const ext = file.name.split(".").pop().toLowerCase();
            if (this.fileType.length && !this.fileType.includes(ext)) {
                this.$message.error(`文件格式不正确，请上传 ${this.fileType.join("/")} 格式文件`);
                return false;
            }
            if (this.fileSize && file.size / 1024 / 1024 >= this.fileSize) {
                this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB`);
                return false;
            }
            this.$loading({ lock: true, text: "正在上传文件，请稍候..." });
            this.number++;
            return true;
        },
        handleExceed() {
            this.$message.error(`上传文件数量不能超过 ${this.limit} 个!`);
        },
        handleUploadError() {
            this.$message.error("上传文件失败");
        },
        handleUploadSuccess(res, file) {
            if (res.code === 200) {
                this.uploadList.push({
                    name: res.data.fileName,
                    url: res.data.url,
                    ossId: res.data.ossId,
                });
                this.uploadedSuccessfully();
            } else {
                this.number--;
                this.$loading().close();
                this.$message.error(res.msg || "上传失败");
                this.$refs.fileUpload.handleRemove(file);
                this.uploadedSuccessfully();
            }
        },
        handleDelete(index) {
            const ossId = this.fileList[index].ossId;
            if (ossId) {
                delOss(ossId);
            }
            this.fileList.splice(index, 1);
            this.$emit("update:modelValue", this.listToString(this.fileList));
        },
        uploadedSuccessfully() {
            if (this.number > 0 && this.uploadList.length === this.number) {
                this.fileList = this.fileList
                    .filter((f) => f.url !== undefined)
                    .concat(this.uploadList);
                this.uploadList = [];
                this.number = 0;
                this.$loading().close();
                this.$emit("update:modelValue", this.listToString(this.fileList));
                this.$emit("over", "success");
                this.$message.success("上传成功");
            }
        },
        getFileName(name) {
            return name.lastIndexOf("/") > -1
                ? name.slice(name.lastIndexOf("/") + 1)
                : name;
        },
        listToString(list, separator = ",") {
            return list
                .filter((item) => item.ossId)
                .map((item) => item.ossId)
                .join(separator);
        },
    },
};
</script>

<style scoped lang="scss">
.upload-file-uploader {
    margin-bottom: 5px;
}

.upload-file-list .el-upload-list__item {
    border: 1px solid #e4e7ed;
    line-height: 2;
    margin-bottom: 10px;
    position: relative;
}

.upload-file-list .ele-upload-list__item-content {
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: inherit;
}

.ele-upload-list__item-content-action .el-link {
    margin-right: 10px;
}
</style>
